/**
 * a class representing a shape defined by a group of points, which connect to each other by straight lines.
 * also, the points creating a closed shape (all the points are "connected from both sides")
 * 
 * a valid polygon is a shape with at least 3 corners!
 * @author Matan Monitz, Nadav Cohen
 *
 */
public abstract class Polygon implements Shape {
	
	private Point points[];			// an array of ORDERED points, representing the ordered corners of the polygon

/**
 * 	Constructor - construct a new Polygon objects based on a group of points.
 * @param points - contains an array of points which represent polygon.
 * 					 degree of the polygon is the length of parameter points.
 * 						(degree of Polygon = the number of sides the Polygon has = the number of points the polygon has).
 * 					 the points of the Polygon are ordered in the object points array. 
 * 					 
 * @exception RuntimeException in case given parameter is null or with less then 3 points (less than 3 corners) - "can't construct wanted polygon"
 */
	public Polygon(Point[] points){
		if(points==null || points.length <= 2)
			throw new RuntimeException("can't construct wanted polygon - given points array uninitialized or not represent a valid polygon (3 corners or more)!");
		this.points = new Point[points.length];
		for(int i=0;i<points.length;i++)	
			this.points[i]= new Point(points[i]);
	}
/**
 * return the number of points the polygon is made of (the degree of the polygon)	
 * @return the number of points the polygon is made of (the degree of the polygon)
 */
	public int getNumOfPoints(){
		return points.length;
	}
/**
 * return the length of the sides of the polygon.	
 * @return an array of double, each cell represent the length of one side of the polygon.
 * 			the sides will be ordered: [0] : points[0]->points[1], [1] : points[1]->points[2], ... , [n] : points[n]->points[0]
 * 			(n is the last point at points array)
 */
	public double[] getSides(){
		double[] sides = new double[points.length];
		for(int i=0;i<sides.length;i++)
			sides[i]=points[i].distance(points[(i+1)%(points.length)]);		//get the distance between each point, also between the last point and the first (in help of modulu)
		return sides;
	}
	
/**
 * return the points forming the Polygon	
 * @return an array of Point, each cell represent a point of the polygon.
 * 			the points in the array are ordered by the sides of the polygon.
 */
	public Point[] getPoints(){
		Point[] temp = new Point[this.points.length];
		for(int i=0;i<this.points.length;i++)	
			temp[i]= new Point(this.points[i]);
		return temp;
	}

	public double getPerimeter() {
		double[] sides=getSides();
		double sum=0;
		for(int i=0;i<sides.length;i++)
			sum=sum+sides[i];
		return sum;
	}

	/**
	 * moves the Polygon according to one of the values of a Point in space
	 * @param p an object of type Point ,the Polygon will be moved acording to the values in space of this point 
	 * @exception RuntimeException in case given parameter is null - "can't move wanted polygon"
	 */
	public void move(Point p)
	{
		if(p==null)
			throw new RuntimeException("can't move wanted polygon - given Point is null!");
		for(int i=0;i<points.length;i++)
			points[i].move(p);
	}

/**
 * compare one polygon to the other to see if its logicly the same (the same Polygon in dimension)
 * @param other - a non primitive object to compare to this Polygon object
 * @return true if parameter logicly equals to this polygon, else return false
 * 	Equals if:
 	* - parameter other is type Polygon and not null
	* - parameter other is the same degree as this Polygon - represented by the same number of points = has the same number of sides 
	* - each corner this polygon has also parameter polygon has (the polygons lies exactly in the same space in two dimenational space)
 */
	public boolean equals(Object other)
	{
		boolean ans=false, foundPoint=false;		//ans - flag for checking objects equality, foundPoint - flag for checking each seperate point
		if(other instanceof Polygon)
		{
			if(((Polygon)other).getNumOfPoints()==this.getNumOfPoints())	//if object other points array not same length as this polygon points array - stop comparing
				ans=true;
			for(int i=0;i<this.getNumOfPoints() && ans;i++)	// check each point at points array
			{
				foundPoint=false;							//initilize flag
				for(int iother=0;iother<((Polygon)other).getNumOfPoints() && !foundPoint;iother++) //compare given point from points to object other points in order to find similiar point
					if( ((Polygon)other).points[iother].equals(points[i]) )							// compare point index i at points array to point at other's points array at index iother.
						foundPoint=true;					//if i point found in object other, continue for next point
				ans=foundPoint;			//if i point not found in object other, than other and this Polygon are different - stop comparing 
			}			
		}
		return ans;
	}
	
	public abstract boolean contains(Point p);
	
	public abstract double getArea();

}